package cn.edu.xmu.javaee.productdemomybatis.dao;

import cn.edu.xmu.javaee.core.exception.BusinessException;
import cn.edu.xmu.javaee.core.model.ReturnNo;
import cn.edu.xmu.javaee.core.util.JacksonUtil;
import cn.edu.xmu.javaee.productdemomybatis.dao.bo.OnSale;
import cn.edu.xmu.javaee.productdemomybatis.dao.bo.Product;
import cn.edu.xmu.javaee.productdemomybatis.mapper.generator.GoodsPoMapper;
import cn.edu.xmu.javaee.productdemomybatis.mapper.generator.ProductPoMapper;
import cn.edu.xmu.javaee.productdemomybatis.mapper.generator.po.GoodsPo;
import cn.edu.xmu.javaee.productdemomybatis.mapper.generator.po.GoodsPoExample;
import cn.edu.xmu.javaee.productdemomybatis.mapper.generator.po.ProductPo;
import cn.edu.xmu.javaee.productdemomybatis.mapper.generator.po.ProductPoExample;
import cn.edu.xmu.javaee.productdemomybatis.util.CloneFactory;
import cn.edu.xmu.javaee.productdemomybatis.util.Common;
import cn.edu.xmu.javaee.productdemomybatis.util.RequestVariables;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.MessageSource;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.stream.Collectors;

import static cn.edu.xmu.javaee.core.model.Constants.PLATFORM;

@Slf4j
@RequiredArgsConstructor
@Repository("separate")
public class SeparateProductDao implements FindProduct{

    private final ProductPoMapper productPoMapper;
    private final OnSaleDao onSaleDao;
    private final GoodsPoMapper goodsPoMapper;

    /**
     * 用MyBatis generator生成的代码实现关联的Product对象
     * @param shopId 商铺id
     * @param productId 产品id
     * @return Product对象，带关联的Product返回
     */
    public Product findById(Integer shopId, Integer productId) throws BusinessException {
        Product product = null;
        try {
            ProductPo productPo = this.findPoById(shopId,productId);
            product = this.getFullProduct(productPo);
            log.debug("findById: product = {}", product);
        } catch (DataAccessException e) {
            log.error(e.getMessage());
            throw new BusinessException(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }
        return product;
    }

    /**
     * 用MyBatis generator生成的代码实现关联的Product对象
     * @param shopId 商铺id 为PLATFROM则在全系统寻找，否则在商铺内寻找
     * @param name 名称
     * @return Product对象列表，带关联的Product返回
     */
    public List<Product> retrieveByName(Integer shopId, String name) throws BusinessException {
        List<Product> productList = new ArrayList<>();
        ProductPoExample example = Common.createExampleByShopIdAndName(shopId, name);
        try {
            List<ProductPo> productPoList = this.productPoMapper.selectByExample(example);
            for (ProductPo po : productPoList) {
                if (Objects.equals(shopId, po.getShopId()) || PLATFORM.equals(shopId)) {
                    Product product = this.getFullProduct(po);
                    productList.add(product);
                }
            }
            log.debug("retrieveByName: productList = {}", productList);
        } catch (DataAccessException e) {
            log.error(e.getMessage());
            throw new BusinessException(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }

        return productList;
    }

    private ProductPo findPoById(Integer shopId, Integer productId){
        ProductPo productPo = this.productPoMapper.selectByPrimaryKey(productId);
        if (Objects.isNull(productPo)) {
            String[] objects = new String[] {"${product}", productId.toString()};
            throw new BusinessException(ReturnNo.RESOURCE_ID_NOTEXIST, JacksonUtil.toJson(objects));
        }
        if (!Objects.equals(shopId, productPo.getShopId()) && !PLATFORM.equals(shopId)){
            String[] objects = new String[] {"${product}", productId.toString(), shopId.toString()};
            throw new BusinessException(ReturnNo.RESOURCE_ID_OUTSCOPE, JacksonUtil.toJson(objects));
        }
        return productPo;
    }

    /**
     * 获得关联的对象
     * @param productPo product po对象
     * @return 关联的Product对象
     * @throws DataAccessException
     */
    private Product getFullProduct(ProductPo productPo) throws DataAccessException {
        assert productPo != null;
        Product product = CloneFactory.copy(new Product(), productPo);
        log.debug("getFullProduct: product = {}",product);
        List<OnSale> latestOnSale = this.onSaleDao.getLatestOnSale(productPo.getId());
        product.setOnSaleList(latestOnSale);

        List<Product> otherProduct = this.retrieveOtherProduct(productPo);
        product.setOtherProduct(otherProduct);
        log.debug("getFullProduct: fullproduct = {}",product);
        return product;
    }

    /**
     * 获得相关的产品对象
     * @param productPo product po对象
     * @return 相关产品对象列表
     * @throws DataAccessException
     */
    private List<Product> retrieveOtherProduct(ProductPo productPo) throws DataAccessException {
        assert productPo != null;
        List<ProductPo> productPoList;
        GoodsPoExample example = new GoodsPoExample();
        GoodsPoExample.Criteria criteria = example.createCriteria();
        criteria.andProductIdEqualTo(productPo.getId());
        List<GoodsPo> goodsPos = this.goodsPoMapper.selectByExample(example);
        List<Integer> productIds = goodsPos.stream().map(GoodsPo::getRelateProductId).collect(Collectors.toList());
        ProductPoExample productPoExample = new ProductPoExample();
        ProductPoExample.Criteria criteria2 = productPoExample.createCriteria();
        criteria2.andIdIn(productIds);
        productPoList = this.productPoMapper.selectByExample(productPoExample);
        return productPoList.stream().map(po -> CloneFactory.copy(new Product(), po)).collect(Collectors.toList());
    }


}
